package com.lk.controller;

import com.alibaba.fastjson2.JSONObject;

import com.lk.entity.Question;
import com.lk.service.QuestionService;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 知识库控制器
 *
 * @author 薄一鸣
 * @date 2024/7/18 19:50
 * @version V1.0
 */
@RestController
public class EsController {

    @Autowired
    RestHighLevelClient client;

    @Autowired
    QuestionService questionService;

    private static final RequestOptions COMMON_OPTIONS = null;

    public static final String QUESTION_INDEX = "question";

    public int autoIncrId;
    /**
     * 启动时获取最大编号
     */




    /**
     * 新增
     * @param map
     * @return
     */

    @PostMapping("add")
    public Map add(@RequestBody Map<String, String> map) {

        Map<String, String> res = new HashMap<>();

        String title = map.get("title");
        String content = map.get("content");

        LocalDateTime now = LocalDateTime.now();

        // 定义日期时间格式化器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 格式化时间
        String createTime = now.format(formatter);

        map.put("create_time",createTime);
        map.put("question_number",questionService.getAutoIncrNum()+"");
        IndexRequest request = new IndexRequest(QUESTION_INDEX);
        request.source(JSONObject.toJSONString(map), XContentType.JSON);
        try {
            IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            res.put("code", "10500");
            res.put("msg", "插入失败");
            return res;
        }
        res.put("code", "0");
        res.put("msg", "插入成功");
        return res;
    }

    /**
     * 更新
     *
     * @param map
     * @return
     */
    @PostMapping("update")
    public Map update(@RequestBody Map<String, String> map) {

        Map<String, String> res = new HashMap<>();

        String title = map.get("title");
        String content = map.get("content");
        String id = map.get("id");

        map.remove("id");
        UpdateRequest updateRequest = new UpdateRequest(
                QUESTION_INDEX, // 索引名
                "_doc",
                id         // 文档ID
        );


        updateRequest.doc(JSONObject.toJSONString(map), XContentType.JSON);

        try {
            UpdateResponse updateResponse = client.update(
                    updateRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            res.put("code", "10500");
            res.put("msg", "修改失败");
            return res;
        }
        res.put("code", "0");
        res.put("msg", "修改成功");
        return res;
    }

    /**
     * 获取
     * @param map
     * @return
     */
    @PostMapping("read")
    public Map read(@RequestBody Map<String, String> map) {

        Map<String, Object> res = new HashMap<>();
        String id = map.get("id");

        try {
            GetRequest getRequest = new GetRequest(
                    QUESTION_INDEX,
                    "_doc",
                    id);


            GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
            if (getResponse.isExists()) {
                Map sourceAsString = getResponse.getSourceAsMap();
                res.put("data", sourceAsString);
            } else {

            }
        } catch (IOException e) {
            res.put("code", "10500");
            res.put("msg", "获取失败");
            return res;
        }
        res.put("code", "0");
        res.put("msg", "获取成功");
        return res;
    }

    /**
     * 删除
     * @param map
     * @return
     */
    @PostMapping("delete")
    public Map delete(@RequestBody Map<String, String> map) {

        Map<String, Object> res = new HashMap<>();
        String id = map.get("id");
        try {
            DeleteRequest deleteRequest = new DeleteRequest(
                    QUESTION_INDEX,
                    "_doc",
                    id);
            DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);

        } catch (IOException e) {
            res.put("code", "10500");
            res.put("msg", "删除失败");
            return res;
        }
        res.put("code", "0");
        res.put("msg", "删除成功");
        return res;
    }

    /**
     * 列表
     * @param map
     * @return
     */
    @PostMapping("list")
    public Map list(@RequestBody Map<String, Object> map) {
        Map<String, Object> res = new HashMap<>();
        int page = 1;
        int pagesize = 20;

        List<String> productList = new ArrayList<>();
        if (map.containsKey("page")) {
            page = Integer.parseInt(map.get("page").toString());
        }

        if (map.containsKey("pagesize")) {
            pagesize = Integer.parseInt(map.get("pagesize").toString());
        }

        if(map.containsKey("product")){
            productList = ( List<String>)map.get("product");
        }
        int from = (page - 1) * pagesize;

        String keyword = map.get("keyword").toString();

        try {

            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title"); // 需要高亮的字段名
            highlightBuilder.field("content"); // 需要高亮的字段名
            highlightBuilder.field("desc"); // 需要高亮的字段名
            highlightBuilder.field("diagnosis"); // 需要高亮的字段名
            highlightBuilder.preTags("<em>"); // 高亮标签的前缀
            highlightBuilder.postTags("</em>"); // 高亮标签的后缀

            SearchRequest searchRequest = new SearchRequest(QUESTION_INDEX);
            // 查询构建
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

            // 查询条件
            if("".equals(keyword) && productList.isEmpty()){

                searchSourceBuilder.query(QueryBuilders.matchAllQuery());
            }else{
                // bool 嵌套查询 外层查询
                BoolQueryBuilder outerBoolQuery  = QueryBuilders.boolQuery();

                if(!"".equals(keyword)){
                    // 取并集
                    BoolQueryBuilder innerBoolQuery1 = QueryBuilders.boolQuery();
                    innerBoolQuery1.should(QueryBuilders.matchQuery("title", keyword));
                    innerBoolQuery1.should(QueryBuilders.matchQuery("content", keyword));
                    outerBoolQuery.must(innerBoolQuery1);
                }

                if(!productList.isEmpty()){
                    BoolQueryBuilder innerBoolQuery2 = QueryBuilders.boolQuery();
                    for(int i = 0; i < productList.size();i++){
                        innerBoolQuery2.should(QueryBuilders.termQuery("product",productList.get(i)));
                    }
                    outerBoolQuery.must(innerBoolQuery2);
                }

                searchSourceBuilder.query(outerBoolQuery);
            }


            // 设置分页
            searchSourceBuilder.from(from);
            searchSourceBuilder.size(pagesize);

            searchRequest.source(searchSourceBuilder);
            // 设置高亮
            searchSourceBuilder.highlighter(highlightBuilder);

            // 返回结果
            SearchResponse  searchResponse= client.search(searchRequest, RequestOptions.DEFAULT);

            List<Question> list = new ArrayList();
            long count = searchResponse.getHits().getTotalHits().value;
            res.put("count", count);
            SearchHit[] hits = searchResponse.getHits().getHits();
            for(SearchHit hit : hits){
                Map<String,Object> tmp = hit.getSourceAsMap();
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();

                HighlightField title = highlightFields.get("title");
                HighlightField content = highlightFields.get("content");
                if (title != null) {
                    Text[] fragments = title.fragments();
                    String fragmentString = fragments[0].string();
                    tmp.put("title",fragmentString);
                    // 使用高亮文本 fragmentString 进行处理
                }

                if (content != null) {
                    Text[] fragments = content.fragments();
                    String fragmentString = fragments[0].string();
                    tmp.put("content",fragmentString);
                    // 使用高亮文本 fragmentString 进行处理
                }

                tmp.put("id",hit.getId());
                list.add(questionService.mapToQuestion(tmp));
            }
            res.put("list", list);

        } catch (IOException e) {
            res.put("code", "10500");
            res.put("msg", "查询失败");
            return res;
        }
        res.put("code", "0");
        res.put("msg", "查询成功");
        return res;
    }

}
